﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;

namespace WooCoo.Authorization
{
    /// <summary>
    /// 服务层端授权规则,表及字段的权限操作
    /// </summary>
    /// <remarks>单件模式创建</remarks>   
    public sealed class AuthorizationManager
    {

        public static readonly AuthorizationManager Instance = new AuthorizationManager();

        private static IAuthorizationProvider _provider;

        /// <summary>
        /// 对象权限
        /// </summary>
        private List<ResourceRight> ObjectRightList { get; set; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        /// <param name="?"></param>
        private AuthorizationManager()
            : this("AuthorizationProvider")
        {
            ObjectRightList = new List<ResourceRight>();
        }

        private AuthorizationManager(string wcdfAuthorizationProviderAppSettingName)
            : this(GetAuthProviderType(wcdfAuthorizationProviderAppSettingName))
        {
        }

        private AuthorizationManager(Type authProviderType)
        {
            if (null == authProviderType)
                throw new ArgumentNullException(Localizer.Active.GetLocalizeString(StringID.PermissionProviderNameNotSpecified));

            if (authProviderType == typeof(NullAuthorizerServciceProvider))
            {
                _provider = null;
                return;
            }

            if (!typeof(IAuthorizationProvider).IsAssignableFrom(authProviderType))
                throw new ArgumentException(string.Format(Localizer.Active.GetLocalizeString(StringID.NotImplementIPermissionProvider), "authProviderType"));

            _provider = (IAuthorizationProvider)Activator.CreateInstance(authProviderType);
        }

        private static Type GetAuthProviderType(string wcdfAuthorizationProviderAppSettingName)
        {
            if (wcdfAuthorizationProviderAppSettingName == null)
                throw new ArgumentNullException(Localizer.Active.GetLocalizeString(StringID.PermissionProviderNameNotSpecified));


            var authProvider = ConfigurationManager.AppSettings[wcdfAuthorizationProviderAppSettingName];

            return string.IsNullOrEmpty(authProvider) ?
              typeof(NullAuthorizerServciceProvider) :
              Type.GetType(authProvider, true);
        }

        public void AddAuthorizationRule(List<ResourceRight> list)
        {
            lock (this.ObjectRightList)
            {
                foreach (ResourceRight or in list)
                {
#if !SILVERLIGHT
                    if (this.ObjectRightList.Exists(o => _provider.Compare(or, o)))
                        continue;
#else
                    if (this.Contains(or))
                        continue;                    
#endif
                    this.ObjectRightList.Add(or);
                }
            }
        }

        /// <summary>
        /// 权限列表是否包含
        /// </summary>
        /// <param name="or"></param>
        /// <returns></returns>
        private bool Contains(ResourceRight or)
        {
            foreach (ResourceRight item in this.ObjectRightList)
            {
                if (_provider.Compare(item, or))
                {
                    return true;
                }
            }
            return false;
        }

        private List<ResourceRight> GetList(string roleID, string objectName)
        {
            return _provider.GetList(roleID, objectName, this.ObjectRightList);
        }

        /// <summary>
        /// 获取指定的对象权限.
        /// </summary>
        /// <param name="roleID">角色ID</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="action">权限种类</param>
        /// <returns>当没有权限控制时.内部的权限提供类为Null</returns>
        public ResourceRight GetOrAddObjectRight(string roleID, string objectName, AuthorizationActions action)
        {
            if (_provider == null)
                return null;
            if (string.IsNullOrEmpty(roleID))
            {
                return null;
            }
            var obList = GetList(roleID, objectName);
            if (obList.Count == 0)
            {
                List<ResourceRight> newlist = _provider.GetObjectRight(ApplicationContext.User.Identity.Name, objectName);
                if (newlist.Count == 0)
                {
                    //如果没有找到对应的控件,则表示不控制.
                    ResourceRight noctrl = _provider.EmptyObjectRight(roleID, objectName);
                    this.ObjectRightList.Add(noctrl);
                    return noctrl;
                }
                else
                {
                    AddAuthorizationRule(newlist);
                }
            }
            return _provider.FindObjectRight(roleID, objectName, action, obList);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roleID"></param>
        /// <param name="ojbectName"></param>
        public void RemoveObjectRight(string roleID)
        {
            //this.ObjectRightList.RemoveAll(op => op.RoleID == roleID);
            //this.ObjectRightList.
            int i = this.ObjectRightList.Count - 1;
            while (i >= 0)
            {
                if (this.ObjectRightList[i].RoleID == roleID)
                    this.ObjectRightList.RemoveAt(i);
                i--;
            }
        }

        /// <summary>
        /// 用户验证
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool Validate(string userName, string password)
        {
            if (_provider == null)
            {
                return false;
            }
            return _provider.Validate(userName, password);
        }
        /// <summary>
        /// Default implementation of the authorizer that
        /// allows all data portal calls to pass.
        /// </summary>
        class NullAuthorizerServciceProvider
        {
            /// <summary>
            /// Creates an instance of the type.
            /// </summary>
            /// <param name="clientRequest">
            /// Client request information.
            /// </param>
            public void Authorize()
            { /* default is to allow all requests */ }
        }
    }
}
